﻿using Microsoft.EntityFrameworkCore;
using MiniFox.Components;
using MiniFox.Data.EntityFramework;
using MiniFox.Infrastructure;
using Sys.Core.Models;
using Sys.Core.Models.Dto;
using Sys.Core.Models.Queries;
using Sys.Core.Models.VO;
using Sys.Core.Providers;

namespace Sys.Data
{
    [AutoResolve]
    public class DictionaryProvider : EntityDataProvider<PlatformDbContext>, IDictionaryProvider
    {
        public ResultObject<IEnumerable<DictionaryGroupVo>> Query(string appId, PagedQueryObject<DictionaryQuery> request)
        {
            var query = (from g in this.CurrentDbContext.SysDict where g.AppId == appId select g);
            var result = this.PagedQueryExecute(query, request);
            return result.GetResultObject(dict => new DictionaryGroupVo
            {
                Id = dict.GroupId,
                Name = dict.GroupName,
                Description = dict.Description,
                Items = (from item in this.CurrentDbContext.SysDictItem
                         where item.AppId == dict.AppId && item.GroupId == dict.GroupId
                         orderby item.Ordinal
                         select new DictionaryItem
                         {
                             Value = item.Value,
                             Text = item.Text,
                             Description = item.Description,
                             Enabled = item.Enabled
                         }).ToArray(),
                CreateTime = dict.CreateTime,
                UpdateTime = dict.UpdateTime
            });
        }

        private DictionaryGroupVo MappingToVo(SysDict dict)
        {
            if (dict == null) return null;
            return new DictionaryGroupVo
            {
                Id = dict.GroupId,
                Name = dict.GroupName,
                Description = dict.Description,
                Items = (from item in this.CurrentDbContext.SysDictItem
                         where item.AppId == dict.AppId && item.GroupId == dict.GroupId
                         orderby item.Ordinal
                         select new DictionaryItem
                         {
                             Value = item.Value,
                             Text = item.Text,
                             Description = item.Description,
                             Enabled = item.Enabled,
                         }).ToArray(),
                CreateTime = dict.CreateTime,
                UpdateTime = dict.UpdateTime
            };
        }

        public DictionaryGroupVo GetItem(string appId, string group)
        {
            var dict = this.CurrentDbContext.SysDict.SingleOrDefault(g => g.AppId == appId && g.GroupId == group);
            return this.MappingToVo(dict);
        }

        public bool Create(string appId, DictionaryGroupDto dto)
        {
            var sysDict = new SysDict();
            sysDict.AppId = appId;
            sysDict.GroupId = dto.Id;
            sysDict.GroupName = dto.Name;
            sysDict.Description = dto.Description;
            sysDict.CreateTime = DateTime.Now;
            sysDict.UpdateTime = DateTime.Now;
            List<BatchOperationItem> list =
            [
                new BatchOperationItem
                {
                    Entity = sysDict,
                    State = EntityState.Added
                },
            ];
            int i = 0;
            foreach(var item in dto.Items)
            {
                var sysDictItem = new SysDictItem();
                sysDictItem.AppId = sysDict.AppId;
                sysDictItem.GroupId = sysDict.GroupId;
                sysDictItem.Value = item.Value;
                sysDictItem.Text = item.Text;
                sysDictItem.Enabled = true;
                sysDictItem.Description = item.Description;
                sysDictItem.Ordinal = i++;
                list.Add(new BatchOperationItem
                {
                    Entity = sysDictItem,
                    State = EntityState.Added
                });
            }
            return this.CommitBatch(list) > 0;
        }

        public bool Update(string appId, DictionaryGroupDto dto)
        {
            var sysDict = this.CurrentDbContext.SysDict.SingleOrDefault(g => g.AppId == appId && g.GroupId == dto.Id);
            if (sysDict == null)
                return false;

            sysDict.GroupName = dto.Name;
            sysDict.Description = dto.Description;
            sysDict.UpdateTime = DateTime.Now;
            List<BatchOperationItem> list =
            [
                new BatchOperationItem
                {
                    Entity = sysDict,
                    State = EntityState.Modified
                },
            ];
            var items = (from d in this.CurrentDbContext.SysDictItem where d.AppId == appId && d.GroupId == dto.Id select d).ToArray();
            list.AddRange(items.Select(d => new BatchOperationItem
            {
                Entity = d,
                State = EntityState.Deleted
            }));

            int i = 0;
            foreach (var item in dto.Items)
            {
                var sysDictItem = new SysDictItem();
                sysDictItem.AppId = sysDict.AppId;
                sysDictItem.GroupId = sysDict.GroupId;
                sysDictItem.Value = item.Value;
                sysDictItem.Text = item.Text;
                sysDictItem.Enabled = true;
                sysDictItem.Description = item.Description;
                sysDictItem.Ordinal = i++;
                list.Add(new BatchOperationItem
                {
                    Entity = sysDictItem,
                    State = EntityState.Added
                });
            }
            return this.CommitBatch(list) > 0;
        }

        public bool Remove(string appId, params string[] groups)
        {
            var items = (from g in this.CurrentDbContext.SysDict where g.AppId == appId && groups.Contains(g.GroupId) select g).ToArray();
            return this.Delete(items) > 0;
        }

        public bool Toggle(string appId, string group, string val)
        {
            var dictItem = this.CurrentDbContext.SysDictItem.SingleOrDefault(i => i.AppId == appId && i.GroupId == group && i.Value == val);
            if (dictItem == null)
                return false;

            dictItem.Enabled = !dictItem.Enabled;
            return this.Update(dictItem) > 0;
        }

    }
}
